
#ifndef SPOOLJOINT_H_
#define SPOOLJOINT_H_

#include "PinJoint.h"

namespace p2
{

class SpoolJoint: public PinJoint
{
DECLARE_RTT(SpoolJoint, PinJoint);

public:
	inline SpoolJoint(Anchor const& a0, Anchor const& pA,
			real radius, real threadLength, bool swapOrder, void* userData);
	virtual ~SpoolJoint();

	static SpoolJoint* create(Anchor const& a0, Anchor const& a1,
			real radius, real lT, bool swapOrder, void* userData);
	static inline SpoolJoint* cast(Constraint* rtt);

	static Vector2<real> computeTangentPoint(Vector2<real> x, real r, real order);
	/*
     * Constraint implementation
     */
    virtual void preStep(real64 dT);
    virtual bool solvePositions(real64 dT);
    virtual bool solveVelocities(real64 dT);
	virtual void computeFutureAnchorPositions(real64 dT);

private:
    real _radius;
    real _order;
	/*
	 * total length of thread
	 */
    real _lT;
    /*
     * length of thread on spool in radians, angle of freedom
     */
    real _radS, _radF;
};

inline SpoolJoint::SpoolJoint(Anchor const& a0, Anchor const& a1, real radius, real lT, bool swapOrder, void* userData)
:	PinJoint(a0, a1, 0.f, userData),
 	_radius(radius),
 	_order(swapOrder?-1.f:+1.f),
 	_lT(lT), _radS(0.f), _radF(0.f)
{
	ASSERTLOG(_radius > 0.f, "SpoolJoint::SpoolJoint");
}

inline SpoolJoint* SpoolJoint::cast(Constraint* rtt)
{
	if (rtt->isA(SpoolJoint::classId())) {
		return (SpoolJoint*) rtt;
	}
	return 0;
}

} /* namespace p2 */

#endif /* SPOOLJOINT_H_ */
